#include"Epoller.hpp"
#include"Socket.hpp"
#include"Log.hpp"
#include<memory>

const uint16_t defaultport=8080;
const int defaultbaklog=32;
const int maxevents=64;
class EpollServer
{
public:
    std::string Str(uint32_t events)
    {
        std::string str;
        if(events&EPOLLIN)str+="EPOLLIN ";
        if(events&EPOLLET)str+="EPOLLET ";
        if(events&EPOLLOUT)str+="EPOLLOUT";
        return str;
    }
    bool Accepter(std::string& peerip,uint16_t peerport)
    {
        int fd = _listensock->AcceptConnection(&peerip, &peerport);
        if (fd < 0)
        {
            lg.LogMessage(Warning, "accept error\n");
            return false;
        }
        lg.LogMessage(Info, "accept success %s:%d \n",peerip,peerport);
        _epoll->Add(fd, EPOLLIN);
        return true;
    }
    int Recv(int fd,std::string *out)
    {
        char buffer[1024];
        int n=recv(fd,buffer,1024,0);
        if(n>0)
        {
            buffer[n]=0;
            *out=buffer;
        }
        return n;
    }
    void HandlerEvents(int events)
    {
        lg.LogMessage(Debug,"%d 个events 已经就绪了\n",events);
        for(int i=0;i<events;i++)
        {
            lg.LogMessage(Debug,"ready fd: %d,Event is: %s\n",_resv[i].data.fd,Str(_resv[i].events).c_str());
            int sockfd=_resv[i].data.fd;
            int event=_resv[i].events;
            if(event&EPOLLIN)
            {
                if (sockfd == _listensock->GetSocket())
                {
                    std::string peerip;
                    uint16_t peerport;
                    bool ret=Accepter(peerip,peerport);
                    if(!ret)
                    {
                        lg.LogMessage(Error,"add fd error...%s : %d\n",strerror(errno),errno);
                        continue;;
                    }
                    lg.LogMessage(Info,"add fd success...\n");
                }
                else
                {
                    std::string message;
                    int n=Recv(sockfd,&message);
                    if(n>0)
                    {
                        lg.LogMessage(Info,"recv message success...\n");
                        std::cout<<"client say# "<<message<<std::endl;
                    }
                    else
                    {
                        if(n==0)
                        {
                            lg.LogMessage(Warning,"client close fd...\n");
                        }
                        else
                            lg.LogMessage(Error,"recv message error...%s : %d\n",strerror(errno),errno);
                        _epoll->DelEvent(sockfd);//epoll移除fd,fd必须是合法的所以要先移除再关闭
                        close(sockfd);
                    }
                }
            }
        }
    }

    EpollServer(int port):_listensock(new Net_Work::TcpSocket()),_epoll(new Epoller()),_is_running(false),_port(port)
    {}
    bool InitServer()
    {
        _listensock->BuildListenSocketMethod(_port,defaultbaklog);
        lg.LogMessage(Info, "init socket success,listensock is,%d\n", _listensock->GetSocket());
        _epoll->InitEpoller();
        lg.LogMessage(Info, "init epoll success\n");
        _epoll->Add(_listensock->GetSocket(),EPOLLIN);
        return true;
    }
    void Loop()
    {
        _is_running=true;
        while(_is_running)
        {
            int timeout=1000;
            int n=_epoll->Wait(_resv,maxevents,timeout);
            switch(n)
            {
                case 0:
                    lg.LogMessage(Debug,"wait timeout...\n");
                    break;
                case -1:
                    lg.LogMessage(Error,"wait error,%s : %d\n",strerror(errno),errno);
                    break;
                default:
                    lg.LogMessage(Info,"wait success...\n");
                    HandlerEvents(n);
                    break;
            }
        }
    }
    ~EpollServer(){}
private:
    std::unique_ptr<Net_Work::Socket> _listensock;
    std::shared_ptr<Epoller> _epoll;
    bool _is_running;
    uint16_t _port;
    struct epoll_event _resv[maxevents];
};